package com.library.management.repository;

import com.library.management.entity.Notification;
import com.library.management.entity.User;
import com.library.management.enums.NotificationPriority;
import com.library.management.enums.NotificationType;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 通知消息数据访问层接口
 * 提供通知消息相关的数据库操作
 *
 * @author 开发者
 * @version 1.0
 * @since 2025-10-20
 */
@Repository
public interface NotificationRepository extends JpaRepository<Notification, Long> {

    // ========== 用户相关查询 ==========

    /**
     * 根据用户查找通知
     *
     * @param user 用户
     * @return 通知列表
     */
    List<Notification> findByUser(User user);

    /**
     * 根据用户ID查找通知
     *
     * @param userId 用户ID
     * @return 通知列表
     */
    List<Notification> findByUserId(Long userId);

    /**
     * 根据用户和阅读状态查找通知
     *
     * @param user 用户
     * @param isRead 是否已读
     * @return 通知列表
     */
    List<Notification> findByUserAndIsRead(User user, Boolean isRead);

    // ========== 状态相关查询 ==========

    /**
     * 根据阅读状态查找通知
     *
     * @param isRead 是否已读
     * @return 通知列表
     */
    List<Notification> findByIsRead(Boolean isRead);

    /**
     * 查找未读通知
     *
     * @return 未读通知列表
     */
    List<Notification> findByIsReadFalse();

    /**
     * 查找用户的未读通知
     *
     * @param userId 用户ID
     * @return 未读通知列表
     */
    List<Notification> findByUserIdAndIsReadFalse(Long userId);

    // ========== 类型和优先级查询 ==========

    /**
     * 根据通知类型查找通知
     *
     * @param type 通知类型
     * @return 通知列表
     */
    List<Notification> findByType(NotificationType type);

    /**
     * 根据优先级查找通知
     *
     * @param priority 优先级
     * @return 通知列表
     */
    List<Notification> findByPriority(NotificationPriority priority);

    /**
     * 根据类型和优先级查找通知
     *
     * @param type 通知类型
     * @param priority 优先级
     * @return 通知列表
     */
    List<Notification> findByTypeAndPriority(NotificationType type, NotificationPriority priority);

    // ========== 时间相关查询 ==========

    /**
     * 查找创建时间在指定范围内的通知
     *
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 通知列表
     */
    List<Notification> findByCreatedTimeBetween(LocalDateTime startTime, LocalDateTime endTime);

    /**
     * 查找过期时间在指定范围内的通知
     *
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 通知列表
     */
    List<Notification> findByExpireTimeBetween(LocalDateTime startTime, LocalDateTime endTime);

    /**
     * 查找已过期的通知
     *
     * @param currentTime 当前时间
     * @return 过期通知列表
     */
    @Query("SELECT n FROM Notification n WHERE n.expireTime IS NOT NULL AND n.expireTime < :currentTime")
    List<Notification> findExpiredNotifications(@Param("currentTime") LocalDateTime currentTime);

    /**
     * 查找有效的通知（未过期）
     *
     * @param currentTime 当前时间
     * @return 有效通知列表
     */
    @Query("SELECT n FROM Notification n WHERE n.expireTime IS NULL OR n.expireTime >= :currentTime")
    List<Notification> findValidNotifications(@Param("currentTime") LocalDateTime currentTime);

    // ========== 复杂查询方法 ==========

    /**
     * 统计用户的未读通知数量
     *
     * @param userId 用户ID
     * @return 未读通知数量
     */
    long countByUserIdAndIsReadFalse(Long userId);

    /**
     * 统计指定类型的通知数量
     *
     * @param type 通知类型
     * @return 通知数量
     */
    long countByType(NotificationType type);

    /**
     * 查找紧急通知（高优先级且未读）
     *
     * @return 紧急通知列表
     */
    @Query("SELECT n FROM Notification n WHERE n.priority = 'URGENT' AND n.isRead = false AND (n.expireTime IS NULL OR n.expireTime >= :currentTime)")
    List<Notification> findUrgentNotifications(@Param("currentTime") LocalDateTime currentTime);

    /**
     * 根据关联业务信息查找通知
     *
     * @param relatedId 关联业务ID
     * @param relatedType 关联业务类型
     * @return 通知列表
     */
    List<Notification> findByRelatedIdAndRelatedType(Long relatedId, String relatedType);

    // ========== 分页查询 ==========

    /**
     * 分页查询用户的通知
     *
     * @param user 用户
     * @param pageable 分页参数
     * @return 分页通知数据
     */
    Page<Notification> findByUser(User user, Pageable pageable);

    /**
     * 分页查询用户的未读通知
     *
     * @param userId 用户ID
     * @param pageable 分页参数
     * @return 分页未读通知
     */
    Page<Notification> findByUserIdAndIsReadFalse(Long userId, Pageable pageable);

    // ========== 更新操作 ==========

    /**
     * 标记通知为已读
     *
     * @param notificationId 通知ID
     */
    @Modifying
    @Query("UPDATE Notification n SET n.isRead = true, n.updatedTime = :currentTime WHERE n.id = :notificationId")
    void markAsRead(@Param("notificationId") Long notificationId, @Param("currentTime") LocalDateTime currentTime);

    /**
     * 批量标记通知为已读
     *
     * @param notificationIds 通知ID列表
     */
    @Modifying
    @Query("UPDATE Notification n SET n.isRead = true, n.updatedTime = :currentTime WHERE n.id IN :notificationIds")
    void markMultipleAsRead(@Param("notificationIds") List<Long> notificationIds,
                            @Param("currentTime") LocalDateTime currentTime);

    /**
     * 删除过期通知
     *
     * @param currentTime 当前时间
     */
    @Modifying
    @Query("DELETE FROM Notification n WHERE n.expireTime IS NOT NULL AND n.expireTime < :currentTime")
    void deleteExpiredNotifications(@Param("currentTime") LocalDateTime currentTime);
}